package com.dz.generator.controller;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import com.alibaba.fastjson.JSON;
import com.dz.generator.constant.JdbcTypeEnum;
import com.dz.generator.constant.TplEnum;
import com.dz.generator.dto.BusCode;
import com.dz.generator.dto.BusResult;
import com.dz.generator.dto.GeneratorDto;
import com.dz.generator.model.ColumnDo;
import com.dz.generator.service.IGeneratorService;
import com.dz.generator.util.MybatisPlusGenerator;
import com.dz.generator.util.VelocityUtil;
import com.dz.generator.util.ZipUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Slf4j
@RestController
public class GeneratorController {

    private static final Map<String,String> tempFileMap = new HashMap<>();

    @Autowired
    private IGeneratorService iGeneratorService;

    @Autowired
    private MybatisPlusGenerator generator;

    @Autowired
    private VelocityUtil velocityUtil;

    @Autowired
    private DataSourceProperties dataSourceProperties;

    @GetMapping("/table")
    public BusResult basetable() {
        String dataName = getTableSchema();
        return BusResult.build(BusCode.SUCCESS, iGeneratorService.findListTable(dataName));
    }

    private String getTableSchema() {
        try {
            URL url = new URL(dataSourceProperties.getUrl().replace("jdbc:mysql","http"));
            String path = url.getPath();
            return path.replaceFirst("/","");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @GetMapping("/filed")
    public BusResult tableCol(@RequestParam String names) {
        List<ColumnDo> list = iGeneratorService.findListColumn(getTableSchema(),names);
        return BusResult.build(BusCode.SUCCESS, list);
    }

    @GetMapping("/template")
    public BusResult template() {
        return BusResult.build(BusCode.SUCCESS, TplEnum.getTplList("0"));
    }

    @GetMapping("/fieldtype")
    public BusResult fieldType() {
        return BusResult.build(BusCode.SUCCESS, JdbcTypeEnum.getList());
    }

    @PostMapping("/generator")
    public BusResult generator(@RequestBody GeneratorDto dto) {
        generator.generatorTpl(dto);
        return BusResult.build(BusCode.SUCCESS);
    }


    @PostMapping("/generatorDtoOrVo")
    public BusResult generatorDtoOrVo(@RequestBody GeneratorDto dto) {
        String key = UUID.randomUUID().toString().replace("-", "");
        File tmpdir = new File(System.getProperty("java.io.tmpdir"), key);
        log.info("{}", tmpdir);
        FileUtil.mkdir(tmpdir);
        dto.setOutputDir(tmpdir.getAbsolutePath()+"/");
        String filePath = velocityUtil.createModel(dto);
        tempFileMap.put(key,filePath);
        return BusResult.build(BusCode.SUCCESS,key);
    }

    @GetMapping("/downloadGenerator")
    public void downloadGenerator(@ModelAttribute GeneratorDto generatorDto, HttpServletResponse response) throws Exception {
        File tmpdir = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString().replace("-", ""));
        try {
            log.info("{}", tmpdir);
            generatorDto.setOutputDir(tmpdir.getAbsolutePath());
            generator.generatorTpl(generatorDto);

            final String[] split = generatorDto.getTableNames().split("\\.");

            String tableSchema = getTableSchema();
            for (String s : split) {
                GeneratorDto temp = new GeneratorDto(generatorDto);
                temp.setName(s);
                temp.setJsonStr(JSON.toJSONString(iGeneratorService.findListColumn(tableSchema,s)));
                temp.setTpls(TplEnum.VO.getLable());
                velocityUtil.createModel(temp);
                temp.setTpls(TplEnum.DTO.getLable());
                velocityUtil.createModel(temp);
            }
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/zip");
            //3.设置content-disposition响应头控制浏览器以下载的形式打开文件
            response.addHeader("Content-Disposition", "attachment;filename=" + UUID.randomUUID().toString().replace("-", "") + ".zip");
            ZipUtil.createZip(tmpdir, response.getOutputStream());
        } finally {
            FileUtil.del(tmpdir.getPath());
        }

    }

    @GetMapping("/download/{fileKey}")
    public void download(@PathVariable String fileKey, HttpServletResponse response) throws RuntimeException {
        String filePath = tempFileMap.get(fileKey);
        if(StringUtils.isEmpty(filePath)){
            log.error("无效的fileKey = {}", fileKey);
            return;
        }
        //提供下载文件前进行压缩，即服务端生成压缩文件
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/octet-stream");
        //3.设置content-disposition响应头控制浏览器以下载的形式打开文件
        response.addHeader("Content-Disposition", "attachment;filename=" + FileNameUtil.getName(filePath));
        try {
            OutputStream out = response.getOutputStream();
            FileReader fileReader = new FileReader(filePath);
            out.write(fileReader.readBytes());
        } catch (IOException e) {
            log.error("文件下载失败 : {}", e.getMessage());
        } finally {
            File file = new File(System.getProperty("java.io.tmpdir"),fileKey);
            if(file.isDirectory()){
                FileUtil.del(file);
            }
        }
    }


    @Deprecated
    @PostMapping("/generatorHtml")
    public BusResult generatorHtml(@RequestBody GeneratorDto dto) {
        velocityUtil.createModel(dto);
        return BusResult.build(BusCode.SUCCESS);
    }


}
